//
//  ViewController.m
//  GCDDemo
//
//  Created by 张敬 on 2019/10/15.
//  Copyright © 2019年 xiuxiu. All rights reserved.
//

#import "ViewController.h"

#ifndef weakify
#if DEBUG
#if __has_feature(objc_arc)
#define weakify(object) autoreleasepool{} __weak __typeof__(object) weak##_##object = object;
#else
#define weakify(object) autoreleasepool{} __block __typeof__(object) block##_##object = object;
#endif
#else
#if __has_feature(objc_arc)
#define weakify(object) try{} @finally{} {} __weak __typeof__(object) weak##_##object = object;
#else
#define weakify(object) try{} @finally{} {} __block __typeof__(object) block##_##object = object;
#endif
#endif
#endif


#ifndef strongify
#if DEBUG
#if __has_feature(objc_arc)
#define strongify(object) autoreleasepool{} __typeof__(object) object = weak##_##object;
#else
#define strongify(object) autoreleasepool{} __typeof__(object) object = block##_##object;
#endif
#else
#if __has_feature(objc_arc)
#define strongify(object) try{} @finally{} __typeof__(object) object = weak##_##object;
#else
#define strongify(object) try{} @finally{} __typeof__(object) object = block##_##object;
#endif
#endif
#endif


@interface ViewController ()
{
    dispatch_semaphore_t semaohoreLock;
    int totalTickets;
}

@end

@implementation ViewController

/**
 1.创建队列
 2.将任务追加到等待的队列中，系统会根据任务的类型执行（串行队列/并行队列）
 */
- (void)viewDidLoad {
    [super viewDidLoad];
    [self gcd_methods_010];
}

/**
 创建队列/将任务追加
 */
- (void)gcd_methods_001{
    //串行队列
    dispatch_queue_t queue_001 = dispatch_queue_create("success_flower_001", DISPATCH_QUEUE_SERIAL);
    //并发队列
    dispatch_queue_t queue_002 = dispatch_queue_create("success_flower_002", DISPATCH_QUEUE_CONCURRENT);
    //全局并发队列
    dispatch_queue_t globalqueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    //主队列
    dispatch_queue_t mainqueue = dispatch_get_main_queue();
    //同步操作
    dispatch_sync(queue_001, ^{
        
    });
    //异步操作
    dispatch_async(queue_002, ^{
        
    });
}


/**
 线程之间的通信
 */
- (void)gcd_methods_002{
    //全局并发队列
    dispatch_queue_t globalqueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    //主队列
    dispatch_queue_t mainqueue = dispatch_get_main_queue();
    
    dispatch_async(globalqueue, ^{
        
        //耗时的任务放到这里
        dispatch_async(mainqueue, ^{
            //得到数据会跟新UI
        });
    });
}

/**
 GCD的栅栏方法
 */
- (void)gcd_methods_003{
    
    //全局并发队列
    dispatch_queue_t globalqueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_async(globalqueue, ^{
        
    });
    dispatch_async(globalqueue, ^{
        
    });
    dispatch_barrier_async(globalqueue, ^{
        
    });
    dispatch_async(globalqueue, ^{
        
    });
    dispatch_async(globalqueue, ^{
        
    });
}

/**
 GCD的组
 */
- (void)gcd_methods_004{
    
    dispatch_queue_t globalqueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_group_t group = dispatch_group_create();
    dispatch_group_async(group, globalqueue, ^{
        
    });
    dispatch_group_async(group, globalqueue, ^{
        
    });
    dispatch_group_async(group, globalqueue, ^{
        
    });
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        
    });
}

/**
快速
 */
- (void)gcd_methods_005{
    dispatch_queue_t globalqueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_apply(6, globalqueue, ^(size_t index) {
        
    });
}

/**
 延迟
 */
- (void)gcd_methods_006{
    
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        
    });
}

/**
 一次
 */
- (void)gcd_methods_007{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        
    });
}

/**
 wait
 */
- (void)gcd_methods_008{
    dispatch_queue_t globalqueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_group_t group = dispatch_group_create();
    dispatch_group_enter(group);
    dispatch_group_async(group, globalqueue, ^{
        dispatch_group_leave(group);
    });
    dispatch_group_async(group, globalqueue, ^{
        
    });
    dispatch_group_async(group, globalqueue, ^{
        
    });
    dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
}

/**
 GCD的信号量/线程同步
 */
- (void)gcd_methods_009{
    __block int number = 1;
    NSLog(@"1 _ %@ : %d", [NSThread currentThread], number);
    dispatch_queue_t globalqueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
    dispatch_async(globalqueue, ^{
        NSLog(@"2 _ %@ : %d", [NSThread currentThread], number);

        [NSThread sleepForTimeInterval:3.0];
        number = 100;
        dispatch_semaphore_signal(semaphore);
        NSLog(@"3 _ %@ : %d", [NSThread currentThread], number);
    });
    
    NSLog(@"4 _ %@ : %d", [NSThread currentThread], number);

    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
    NSLog(@"5 _ %@ : %d", [NSThread currentThread], number);
}


/**
 线程安全/线程加锁
 */
- (void)gcd_methods_010{
    
    semaohoreLock = dispatch_semaphore_create(1);
    totalTickets = 50;
    
    dispatch_queue_t queue_001 = dispatch_queue_create("success_flowers_001", DISPATCH_QUEUE_SERIAL);
    dispatch_queue_t queue_002 = dispatch_queue_create("success_flowers_002", DISPATCH_QUEUE_SERIAL);
    
    @weakify(self);
    dispatch_async(queue_001, ^{
        @strongify(self);
        [self sellTickets];
    });
    
    dispatch_async(queue_002, ^{
         @strongify(self);
        [self sellTickets];
    });
    
}

- (void)sellTickets{
    
    while (1) {
        
        dispatch_semaphore_wait(semaohoreLock, DISPATCH_TIME_FOREVER);
        if (totalTickets >0) {
            totalTickets--;
            NSLog(@"还剩余%d张票， %@", totalTickets, [NSThread currentThread]);
            [NSThread sleepForTimeInterval:2.0];
        }else{
            NSLog(@"票已售完");
            dispatch_semaphore_signal(semaohoreLock);
            break;
        }
        dispatch_semaphore_signal(semaohoreLock);
    }
    
}




@end
